#include "Test2_var.hh"
#include "plato_node_factory.hh"
#include <unordered_map>
#include <string>

static std::unordered_map<plato::VarID, std::size_t> var_creator_size_map = {
  {1, sizeof(plato::String)},
};

static std::unordered_map<plato::VarID, std::string> var_id_name_map = {
  {1,"Message"},
};


namespace plato { namespace Test2 {

using VarCreator = VariablePtr(*)(DomainPtr, plato::PlatoVariableSyncType);

auto create_Message(DomainPtr domain_ptr, plato::PlatoVariableSyncType sync_type) -> VariablePtr {
  auto ptr = domain_ptr->NewNoIdentified<String>(sync_type);
  auto impl_ptr = std::dynamic_pointer_cast<VariableImpl>(ptr);
  impl_ptr->set_id(1);
  ptr->set_default("Hello world");
  domain_ptr->identify(ptr);
  return ptr;
}

static std::unordered_map<plato::VarID, VarCreator> var_creator_map = {
  {1, create_Message},
};

}}

auto plato::Test2::create_variable(plato::VarID var_id, DomainPtr domain_ptr, plato::PlatoVariableSyncType sync_type) -> VariablePtr {
  auto it = var_creator_map.find(var_id);
  if (it == var_creator_map.end()) { return nullptr; }
  return (*(it->second))(domain_ptr, sync_type);
}

auto plato::Test2::query_variable_size(plato::VarID var_id) -> std::size_t {
  auto it = var_creator_size_map.find(var_id);
  if (it == var_creator_size_map.end()) { return 0; }
  return it->second;
}

auto plato::Test2::get_var_name(plato::VarID var_id) -> const std::string& {
  static std::string NullString;
  auto it = var_id_name_map.find(var_id);
  if (it == var_id_name_map.end()) { return NullString; }
  return it->second;
}

extern auto add_var_creator(const char* name, VarCreatorFunc func, VarCreatorSizeFunc size_func) -> bool;
bool res_Test2 = add_var_creator("Test2", plato::Test2::create_variable, plato::Test2::query_variable_size);
extern auto add_var_name_query(const char *name, VarNameQueryFunc func) -> bool;
bool query_Test2 = add_var_name_query("Test2", plato::Test2::get_var_name);
